package jmine.tec.database.query;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;

import org.hibernate.jdbc.Work;

/**
 * Carregador de metadados de colunas
 * 
 * @author lundberg
 */
public class ColumnLoader implements Callable<Map<String, Column>> {

    private final Database database;

    private final Table table;

    /**
     * Construtor
     * 
     * @param database database
     * @param table table
     */
    public ColumnLoader(Database database, Table table) {
        this.database = database;
        this.table = table;
    }

    /**
     * {@inheritDoc}
     */
    public Map<String, Column> call() {
        final Map<String, Column> columns = new TreeMap<String, Column>();
        this.database.doWork(new Work() {
            public void execute(Connection connection) throws SQLException {
                String schema = ColumnLoader.this.database.getSchema();
                String tableName = ColumnLoader.this.table.getName();
                this.readColumns(connection, schema, tableName, null);
                if (schema != null) {
                    this.readColumns(connection, schema.toUpperCase(), tableName, "%");
                }
            }

            /**
             * @param columns columns
             * @param connection connection
             * @param schema schema
             * @param tableName tableName
             * @throws SQLException SQLException
             */
            private void readColumns(Connection connection, String schema, String tableName, String columnPattern) throws SQLException {
                ResultSet rs = null;
                try {
                    rs = connection.getMetaData().getColumns(null, schema, tableName, columnPattern);
                    while (rs.next()) {
                        int type = rs.getInt("DATA_TYPE");
                        ColumnFactory factory = ColumnLoader.this.database.getColumnFactories().get(type);
                        if (factory != null) {
                            String name = rs.getString("COLUMN_NAME");
                            if (!columns.containsKey(name)) {
                                Column column = factory.create(type, name);
                                columns.put(name, column);
                            }
                        }
                    }
                } finally {
                    DatabaseUtil.closeQuietly(rs);
                }
            }
        });
        return columns;
    }
}
